package com.wosiliujing.learning.util;

import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.wosiliujing.learning.entity.TreeNode;
import lombok.experimental.UtilityClass;
import org.springframework.beans.BeanUtils;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 树工具类
 * @author 刘靖
 * @date 2020/6/5 9:22
 */
@UtilityClass
public class TreeUtil {

    /**
     * 构建树
     * @param  treeNodes 所有树节点
     * @param root 跟节点
     * @param <T> treeNode子类
     * @return 组装树
     */
    public <T extends TreeNode> List<T> buildTree(List<T> treeNodes, Object root){
        List<T> trees = new ArrayList<>();
        for(T treeNode : treeNodes){
            if(ObjectUtil.equal(root,treeNode.getParentId())){
                trees.add(findChildren(treeNodes,treeNode));
            }
        }
        return trees;
    }

    /***
     * 将实体转换成树
     * @author 刘靖
     * @date 2020/6/5 9:24
     * @param entityList 需要转换的实体
     * @param targetTress 需要转换的目标树
     * @param root 跟节点
     * @return 转换后的组装树
     */
    @SuppressWarnings("unchecked")
    public <T extends TreeNode, R> List<T> convertToTree(List<R> entityList, T targetTress, String root){
        List<T> treeList = entityList.stream()
                .map(entity -> {
                    T tree ;
                    try {
                        tree = (T)targetTress.getClass().newInstance();
                        BeanUtils.copyProperties(entity,tree);
                        return tree;
                    } catch (InstantiationException | IllegalAccessException e) {
                        e.printStackTrace();
                    }
                    return null;
                }).collect(Collectors.toList());
        return buildTree(treeList,root);
    }

    /**
     * 递归组装树
     * @param treeNodes 所有树节点
     * @param treeNode 当前树节点
     * @param <T> treeNode子类
     * @return 组装树
     */
    private  <T extends TreeNode> T findChildren(List<T> treeNodes, T treeNode){
        treeNodes.forEach( tree -> {
            if(StrUtil.equals(treeNode.getId(),tree.getParentId())){
                if(ObjectUtil.isNull(treeNode.getChildren())){
                   treeNode.setChildren(new ArrayList<>());
                }
                treeNode.add(findChildren(treeNodes,tree));
            }
        });
        return treeNode;
    }
}
